#include <Windows.h>
#include <stdio.h>
#include <string>
#include "h2base.h"
#pragma once


#define MAX_LOG_SIZE    1000000     // Default max log size = 1MB, 
                                    // which is available for log, debug and error as well
#define MAX_STR_BUF     65535       // Maximum log length could be writen each 

#define ERR_CODE_OTHER  -1          // default error code
#define ERR_CODE_PARAM  -2          // function parameter error
#define ERR_CODE_SYSTEM -3          // system error
#define ERR_CODE_CONFIG -4          // configuration error
#define ERR_CODE_FORMAT -5          // xml or text format error

#define DEBUG_ALL       0xFFFFFFFF
#define DEBUG_RESERVED  0xF0000000  // bit 1 ~ 8    are reserved
#define DEBUG_ALL_LVL   0x0F000000  // bit 9 ~ 16   for debug levels
#define DEBUG_ALL_SYS   0x00FF0000  // bit 17 ~ 32  for system modules
#define DEBUG_ALL_APP   0x0000FFFF  // bit 33 ~ 64  for applications

// Debug levels
#define DEBUG_L1        0x01000000  // bit 16 : system info level - few
#define DEBUG_L2        0x02000000  // bit 15 : system flow level - normal
#define DEBUG_L3        0x04000000  // bit 14 : function process level - detail
#define DEBUG_L4        0x08000000  // bit 13 : application level - detail

// System modules                                    bit 17 ~ 32
#define DEBUG_WIN       0x00800000  // bit 17      : 1000 0000 0000 0000
#define DEBUG_FRAME     0x00C00000  // bit 17 & 18 : 1100 0000 0000 0000
#define DEBUG_SPLITTER  0x00A00000  // bit 17 & 19 : 1010 0000 0000 0000
#define DEBUG_EDIT      0x00900000  // bit 17 & 20 : 1001 0000 0000 0000
#define DEBUG_SOCKET    0x00008000  // bit 25      : 0000 0000 1000 0000
#define DEBUG_HTTP      0x0000C000  // bit 25 & 26 : 0000 0000 1100 0000


class file_log
{
public:
    file_log() : _fp(NULL), _max_file_size(MAX_LOG_SIZE), _backup_days(30) { _filename = L""; }
    ~file_log()                             { close(); }

    void set_filename(const wchar_t* filename) { if(filename) _filename = filename; } 
    void set_max_size(unsigned long size)   { _max_file_size = size; }
    void set_backup_days(int days)          { _backup_days = days; }
    const wchar_t* get_filename()           { return *_filename; } 

    bool open()                             { close(); return 0 == _wfopen_s(&_fp, *_filename, L"a+"); }
    void close()                            { if(_fp) { fclose(_fp); _fp = NULL; } }
    bool write(const char* pzlog);
    bool backup_log();

private:
    FILE*           _fp;
    STRING::unicode _filename;
    unsigned long   _max_file_size;
    int             _backup_days;

};



class LOG
{
private:
    LOG()       {}
    ~LOG()      {}

public:
    typedef  bool (* output_func)(const wchar_t* pwzmsg);
    static void     set_output_func(output_func func)       { _output_func = func; }
    static bool     output(const wchar_t* pwzlog)           { if(_output_func) return (*_output_func)(pwzlog); return true; }

    // error and normal log all will be written into log file
    static bool     log(const char* pzlog, ...);

    // error message will call log() first, and then a speciall process follows.
    // e.g. Write an individual error file allows app to do an error recycling process.
    static bool     error(int error_code, const char* pzerror, ...);

    // debug message only be displayed when iDebugFlag matched
    static bool     debug(int debug_flag, const char* pzdebug, ...);

    // enable or disable debug messages
    static void     set_debug_flag(int debug_flag = DEBUG_ALL)  { _debug_flag = debug_flag; }

public:
    static  file_log            log_file, debug_file, error_file;

private:
    static  int                 _debug_flag;
    static  output_func         _output_func;
};
